package safecontainer

import (
	"runtime"
	"sync/atomic"
)

// SafeListTNode 节点
type SafeListTNode[T any] struct {
	next  atomic.Pointer[SafeListTNode[T]]
	value T
}

// SafeListT 安全链表
type SafeListT[T any] struct {
	head atomic.Pointer[SafeListTNode[T]]
	tail atomic.Pointer[SafeListTNode[T]]

	C chan bool

	vnil T
}

// NewSafeListT 新创建一个列表
/*
给一个nil值对象进来
*/
func NewSafeListT[T any]() *SafeListT[T] {

	result := &SafeListT[T]{
		C: make(chan bool, 1),
	}
	node := new(SafeListTNode[T])
	result.head.Store(node)
	result.tail.Store(node)
	return result
}

func (sl *SafeListT[T]) newNode(data T) (result *SafeListTNode[T]) {
	result = new(SafeListTNode[T])
	result.value = data
	return
}

// Put 放入
func (sl *SafeListT[T]) Put(data T) {
	newNodeT := sl.newNode(data)
	var tail *SafeListTNode[T]

	for {
		tail = sl.tail.Load()
		next := tail.next.Load()

		if next != nil {
			sl.tail.CompareAndSwap(tail, next)
		} else {
			if sl.tail.Load().next.CompareAndSwap(nil, newNodeT) {
				break
			}
		}
		runtime.Gosched()
	}
	sl.tail.CompareAndSwap(tail, newNodeT)

	select {
	case sl.C <- true:
	default:
	}
}

// Pop 拿出
func (sl *SafeListT[T]) Pop() (result T, err error) {

	for {
		head := sl.head.Load()
		tail := sl.tail.Load()

		next := head.next.Load()

		if head == tail {
			if next == nil {
				return sl.vnil, errNoNode
			}
			sl.tail.CompareAndSwap(tail, next)
		} else {
			if sl.head.CompareAndSwap(head, next) {
				result = next.value
				next.value = sl.vnil
				return result, nil
			}
		}
		runtime.Gosched()
	}

}

// IsEmpty 是否为空
func (sl *SafeListT[T]) IsEmpty() bool {
	head := sl.head.Load()
	tail := sl.tail.Load()
	next := head.next.Load()
	if head == tail {
		if next == nil {
			return true
		}
	}

	return false
}
